关于 Kubernetes中kube-controller-manager的一些笔记

我想变成一棵树. 开心时在秋天开花; 伤心时在春天落叶。 ——烽火戏诸侯《剑来》

写在前面


  • 学习K8s,遇到整理记忆
  • 大部分都是书里或者官网的东西
  • 博文内容为kube-controller-manager的一些理论
  • 涉及到常见控制器的一些说明

我想变成一棵树. 开心时在秋天开花; 伤心时在春天落叶。 ——烽火戏诸侯《剑来》


Kubernetes 控制器管理器是一个守护进程,内嵌随 Kubernetes 一起发布的核心控制回路控制回路是一个永不休止的循环(所以说K8S中的控制管理器是一个死循环),用于调节系统状态。

在 Kubernetes 中,每个控制器是一个控制回路,通过 API 服务器监视集群的共享状态, 并尝试进行更改以将当前状态转为期望状态。 目前,Kubernetes 自带的控制器例子包括副本控制器节点控制器命名空间控制器服务账号控制器等。

Controller Manager 原理分析

Controller Manager作为集群内部的管理控制中心,当某个Node意外宕机时, Controller Manager会及时发现此故障并执行自动化修复流程,确保集群始终处于预期的工作状态

Controller Manager内部包含Replication Controller, Node Controller, ResourceQuota Controller, Namespace Controller, ServiceAccount Controller, Token Controller,Service ControllerEndpoint Controller等多个Controller,每种Controller都负责一种具体的控制流程,而Controller Manager正是这些Controller的核心管理者。

副本控制器(Replication Controller)

其实对这个有些模糊,RC资源现在用的已经很少了,不知道这里只是指RC还是说RS,deploy都是由Replication Controller控制的

Replication Controller的核心作用是确保在任何时候集群中一个RC所关联的Pod副本数量保持预设值

需要注意的一点是: 只有当Pod的重启策略是Always时(RestartPolicy=Always), Replication Controller才会管理该Pod的操作(例如创建、销毁、重启等)

RC 中的pod模板一旦创建完成,就和RC中的模板没有任何关系。 Pod可以通过修改标签来实现脱离RC的管控。可以用于 **将Pod从集群中迁移、数据修复等调试**。

对于被迁移的Pod副本, RC会自动创建一个新的,副本替换被迁移的副本。需要注意的是,删除一个RC不会影响它所创建的Pod,如果想删除一个RC所控制的Pod,则需要将该RC的副本数(Replicas)属性设置为0,这样所有的Pod副本都会被自动删除。

Replication Controller的职责:

Replication Controller的职责
确保当前集群中有且仅有N个Pod实例, N是RC中定义的Pod副本数量。
通过调整RC的spec.replicas属性值来实现系统扩容或者缩容。
通过改变RC中的Pod模板(主要是镜像版本)来实现系统的滚动升级。

使用场景

使用场景
重新调度(Rescheduling):副本控制器都能确保指定数量的副本存在于集群中
弹性伸缩(Scaling),手动或者通过自动扩容代理修改副本控制器的spec.replicas属性值,非常容易实现扩大或缩小副本的数量。
滚动更新(Rolling Updates),副本控制器被设计成通过逐个替换Pod的方式来辅助服务的滚动更新。即现在的deployment资源的作用,通过新旧两个RC 实现滚动更新

节点控制器(Node Controller)

kubelet进程在启动时通过API Server向master注册自身的节点信息,并定时向API Server汇报状态信息, API Server接收到这些信息后,将这些信息更新到etcd中, etcd中存储的节点信息包括节点健康状况节点资源节点名称节点地址信息操作系统版本Docker版本kubelet版本等

节点健康状况包含“就绪” (True) “未就绪” (False)“未知" (Unknown)三种。

Node Controller通过API Server实时获取Node的相关信息,实现管理和监控集群中的各个Node节点的相关控制功能, Node Controller的核心工作流程如图。

Node Controller的核心工作流程如图
在这里插入图片描述

Controller Manager在启动时如果设置了-cluster-cidr参数,那么为每个没有设置Spec.PodCIDR的Node节点生成一个CIDR地址,并用该CIDR地址设置节点的Spec.PodCIDR属性,这样做的目的是防止不同节点的CIDR地址发生冲突。

逐个读取节点信息,多次尝试修改nodestatusMap中的节点状态信息,将该节点信息和Node ControllernodeStatusMap中保存的节点信息做比较。

节点状态
如果判断出没有收到kubelet发送的节点信息、第1次收到节点kubelet发送的节点信息,或在该处理过程中节点状态变成非“健康”状态
则在nodeStatusMap中保存该节点的状态信息,并用Node Controller所在节点的系统时间作为探测时间和节点状态变化时间。
如果判断出在指定时间内收到新的节点信息,且节点状态发生变化
则在nodeStatusMap中保存该节点的状态信息,并用NodeController所在节点的系统时间作为探测时间和节点状态变化时间。
如果判断出在指定时间内收到新的节点信息,但节点状态没发生变化
则在nodeStatusMap中保存该节点的状态信息,并用Node Controller所在节点的系统时间作为探测时间,用上次节点信息中的节点状态变化时间作为该节点的状态变化时间。
如果判断出在某一段时间(gracePeriod)内没有收到节点状态信息
设置节点状态为“未知” (Unknown),并且通过API Server保存节点状态
如果节点状态变为非“就绪”状态
则将节点加入待删除队列,否则将节点从该队列中删除

如果节点状态为非“就绪”状态,且系统指定了Cloud Provider,则Node Controller 调用Cloud Provider查看节点,若发现节点故障,则删除etcd中的节点信息,并删除和该节点相关的Pod等资源的信息。

资源控制器(ResourceQuota Controller)

Kubernetes提供了资源配额管理( ResourceQuotaController),确保了指定的资源对象在任何时候都不会超量占用系统物理资源,导致整个系统运行紊乱甚至意外宕机,对整个集群的平稳运行和稳定性有非常重要的作用。

Kubernetes支持资源配额管理。

配置级别
容器级别,可以对CPU和Memory进行限制。
Pod级别,可以对一个Pod内所有容器的可用资源进行限制。
Namespace级别,为Namespace (多租户)级别的资源限制,Pod数量;Replication Controller数量; Service数量;ResourceQuota数量;Secret 数量;可持有的PV (Persistent Volume)数量。

Kubernetes的配额管理是通过Admission Control (准入控制)来控制的, Admission Control当前提供了两种方式的配额约束,分别是LimitRangerResourceQuota。其中

  • LimitRanger作用于Pod和Container上,
  • ResourceQuota则作用于Namespace上,限定一个Namespace里的各类资源的使用总额。

如果在Pod定义中同时声明了LimitRanger,则用户通过API Server请求创建或修改资源时, Admission Control会计算当前配额的使用情况,如果不符合配额约束,则创建对象失败。

对于定义了ResourceQuotaNamespace, ResourceQuota Controller组件则负责定期统计和生成该Namespace下的各类对象的资源使用总量,统计结果包括Pod, Service,RC、Secret和Persistent Volume等对象实例个数,以及该Namespace下所有Container实例所使用的资源量(目前包括CPU和内存),然后将这些统计结果写入etcdresourceQuotaStatusStorage目录(resourceQuotas/status)中。

ResourceQuota Controller 流程圖
在这里插入图片描述

命名空间(Namespace Controller)

通过API Server可以创建新的Namespace并保存在etcd中, Namespace Controller定时通过API Server读取这些Namespace信息。

删除步骤
如果Namespace被API标识为优雅删除(通过设置删除期限,即DeletionTimestamp属性被设置),则将该NameSpace的状态设置成”Terminating“并保存到etcd中。同时Namespace Controller删除该Namespace下的ServiceAccount, RC, Pod.Secret, PersistentVolume, ListRange, ResourceQuota和Event等 **资源对象**。
Namespace的状态被设置成”Terminating“后,由Admission ControllerNamespaceLifecycle插件来 阻止 为该Namespace创建新的资源。
Namespace Controller删除完该Namespace中的所有资源对象后, Namespace Controller对该Namespace执行finalize操作,删除Namespacespec.finalizers域中的信息
如果Namespace Controller观察到Namespace设置了删除期限,同时Namespace的spec.finalizers域值是空的,那么Namespace Controller将通过API Server删除该Namespace资源

Service Controller(服务控制器)与Endpoint Controller

Service, Endpoints与Pod的关系

Endpoints表示一个Service对应的所有Pod副本的访问地址,而EndpointsController就是负责生成和维护所有Endpoints对象的控制器。

在这里插入图片描述

Endpoint Controller负责监听Service和对应的Pod副本的变化

Endpoint Controller监听
如果监测到Service被删除,则删除和该Service同名的Endpoints对象。
如果监测到新的Service被创建或者修改,则根据该Service信息获得相关的Pod列表,然后创建或者更新Service对应的Endpoints对象。
如果监测到Pod的事件,则更新它所对应的Service的Endpoints对象(增加、删除或者修改对应的Endpoint条目)

Endpoints对象是在哪里被使用的呢?

每个Node上的kube-proxy进程,kube-proxy进程获取每个ServiceEndpoints,实现了Service负载均衡功能。

Service Controller的作用,它其实是属于Kubernetes集群与外部的云平台之间的一个接口控制器

Service Controller监听Service的变化,如果是一个LoadBalancer类型的Service (externalLoadBalancers-true),则Service Controller确保外部的云平台上该Service对应的LoadBalancer实例被相应地创建、删除及更新路由转发表(根据Endpoints的条目)。

yaml 资源文件

相关启动参数小伙伴可以移步官网查看: https://kubernetes.io/zh/docs/reference/command-line-tools-reference/kube-controller-manager/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create]
└─$kubectl get pods kube-controller-manager-vms81.liruilongs.github.io -o yaml -n kube-system
apiVersion: v1
kind: Pod
metadata:
annotations:
kubernetes.io/config.hash: 49b7654103f80170bfe29d034f806256
kubernetes.io/config.mirror: 49b7654103f80170bfe29d034f806256
kubernetes.io/config.seen: "2021-12-14T23:02:32.958181106+08:00"
kubernetes.io/config.source: file
seccomp.security.alpha.kubernetes.io/pod: runtime/default
creationTimestamp: "2021-12-14T15:02:33Z"
labels:
component: kube-controller-manager
tier: control-plane
name: kube-controller-manager-vms81.liruilongs.github.io
namespace: kube-system
ownerReferences:
- apiVersion: v1
controller: true
kind: Node
name: vms81.liruilongs.github.io
uid: b1e00933-c091-4a1f-b470-1418cbe5bc20
resourceVersion: "296478"
uid: ac955a42-0c15-44f8-9217-cacc59c8f410
spec:
containers:
- command:
- kube-controller-manager
- --allocate-node-cidrs=true
- --authentication-kubeconfig=/etc/kubernetes/controller-manager.conf
- --authorization-kubeconfig=/etc/kubernetes/controller-manager.conf
- --bind-address=127.0.0.1
- --client-ca-file=/etc/kubernetes/pki/ca.crt
- --cluster-cidr=10.244.0.0/16
- --cluster-name=kubernetes
- --cluster-signing-cert-file=/etc/kubernetes/pki/ca.crt
- --cluster-signing-key-file=/etc/kubernetes/pki/ca.key
- --controllers=*,bootstrapsigner,tokencleaner
- --kubeconfig=/etc/kubernetes/controller-manager.conf
- --leader-elect=true
- --port=0
- --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt
- --root-ca-file=/etc/kubernetes/pki/ca.crt
- --service-account-private-key-file=/etc/kubernetes/pki/sa.key
- --service-cluster-ip-range=10.96.0.0/12
- --use-service-account-credentials=true
image: registry.aliyuncs.com/google_containers/kube-controller-manager:v1.22.2
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 8
httpGet:
host: 127.0.0.1
path: /healthz
port: 10257
scheme: HTTPS
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 15
name: kube-controller-manager
resources:
requests:
cpu: 200m
startupProbe:
failureThreshold: 24
httpGet:
host: 127.0.0.1
path: /healthz
port: 10257
scheme: HTTPS
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 15
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /etc/ssl/certs
name: ca-certs
readOnly: true
- mountPath: /etc/pki
name: etc-pki
readOnly: true
- mountPath: /usr/libexec/kubernetes/kubelet-plugins/volume/exec
name: flexvolume-dir
- mountPath: /etc/kubernetes/pki
name: k8s-certs
readOnly: true
- mountPath: /etc/kubernetes/controller-manager.conf
name: kubeconfig
readOnly: true
dnsPolicy: ClusterFirst
enableServiceLinks: true
hostNetwork: true
nodeName: vms81.liruilongs.github.io
preemptionPolicy: PreemptLowerPriority
priority: 2000001000
priorityClassName: system-node-critical
restartPolicy: Always
schedulerName: default-scheduler
securityContext:
seccompProfile:
type: RuntimeDefault
terminationGracePeriodSeconds: 30
tolerations:
- effect: NoExecute
operator: Exists
volumes:
- hostPath:
path: /etc/ssl/certs
type: DirectoryOrCreate
name: ca-certs
- hostPath:
path: /etc/pki
type: DirectoryOrCreate
name: etc-pki
- hostPath:
path: /usr/libexec/kubernetes/kubelet-plugins/volume/exec
type: DirectoryOrCreate
name: flexvolume-dir
- hostPath:
path: /etc/kubernetes/pki
type: DirectoryOrCreate
name: k8s-certs
- hostPath:
path: /etc/kubernetes/controller-manager.conf
type: FileOrCreate
name: kubeconfig
status:
conditions:
- lastProbeTime: null
lastTransitionTime: "2021-12-20T00:28:14Z"
status: "True"
type: Initialized
- lastProbeTime: null
lastTransitionTime: "2021-12-21T13:10:56Z"
status: "True"
type: Ready
- lastProbeTime: null
lastTransitionTime: "2021-12-21T13:10:56Z"
status: "True"
type: ContainersReady
- lastProbeTime: null
lastTransitionTime: "2021-12-20T00:28:14Z"
status: "True"
type: PodScheduled
containerStatuses:
- containerID: docker://6af720a0409f3bb3ffd8ddd7995faf749c43145fea39f28ff54a235f4644385b
image: registry.aliyuncs.com/google_containers/kube-controller-manager:v1.22.2
imageID: docker-pullable://registry.aliyuncs.com/google_containers/kube-controller-manager@sha256:91ccb477199cdb4c63fb0c8fcc39517a186505daf4ed52229904e6f9d09fd6f9
lastState:
terminated:
containerID: docker://5b5e8d4cc06d08ecd4d5940e3cdceb55728c410738698c14d144c454772cb17e
exitCode: 255
finishedAt: "2021-12-21T13:10:04Z"
reason: Error
startedAt: "2021-12-21T00:31:52Z"
name: kube-controller-manager
ready: true
restartCount: 19
started: true
state:
running:
startedAt: "2021-12-21T13:10:32Z"
hostIP: 192.168.26.81
phase: Running
podIP: 192.168.26.81
podIPs:
- ip: 192.168.26.81
qosClass: Burstable
startTime: "2021-12-20T00:28:14Z"

发布于

2021-12-21

更新于

2023-06-21

许可协议

评论
Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×